package edu.ilstu.mind.ise.ccp.message.hashmap;

import java.util.HashMap;
import java.util.Map;

import edu.ilstu.mind.ise.ccp.message.MessageFieldFormatException;
import edu.ilstu.mind.ise.ccp.message.MutableMessage;

public class HashMapMutableMessage implements MutableMessage {
	
	private final String from;
	private final String to;
	private final Map<String, Object> map;
	private boolean finalized = false;
	
	public HashMapMutableMessage(String from, String to, int numFields) {
		this.from = from;
		this.to = to;
		map = new HashMap<String, Object>(numFields);
	}

	@Override
	public String getFrom() {
		return from;
	}

	@Override
	public String getTo() {
		return to;
	}
	
	@Override
	public void finalizeMessage() {
		this.finalized = true;
	}
	
	@Override
	public byte[] getBytesField(String key) throws MessageFieldFormatException {
		Object value = map.get(key);
		if(!(value instanceof byte[])) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Byte Array. It is of type " + key.getClass());
		}
		return (byte[])value;
	}

	@Override
	public String getStringField(String key) {
		Object value = map.get(key);
		if(!(value instanceof String)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a String. It is of type " + key.getClass());
		}
		return (String)value;
	}
	
	@Override
	public boolean getBooleanField(String key) throws MessageFieldFormatException {
		Object value = map.get(key);
		if(!(value instanceof Boolean)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Boolean. It is of type " + key.getClass());
		}
		return (Boolean)value;
	}

	@Override
	public byte getByteField(String key) {
		Object value = map.get(key);
		if(!(value instanceof Byte)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Byte. It is of type " + key.getClass());
		}
		return (Byte)value;
	}

	@Override
	public char getCharField(String key) {
		Object value = map.get(key);
		if(!(value instanceof Character)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Character. It is of type " + key.getClass());
		}
		return (Character)value;
	}

	@Override
	public short getShortField(String key) {
		Object value = map.get(key);
		if(!(value instanceof Short)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Short. It is of type " + key.getClass());
		}
		return (Short)value;
	}

	@Override
	public int getIntField(String key) {
		Object value = map.get(key);
		if(!(value instanceof Integer)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not an Integer. It is of type " + key.getClass());
		}
		return (Integer)value;
	}

	@Override
	public long getLongField(String key) throws NumberFormatException {
		Object value = map.get(key);
		if(!(value instanceof Long)) {
			throw new MessageFieldFormatException("<" + key + "=" + value + "> is not a Long. It is of type " + key.getClass());
		}
		return (Long)value;
	}

	@Override
	public void setField(String key, byte[] value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}
	
	@Override
	public void setField(String key, String value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}

	@Override
	public void setField(String key, boolean value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}
	
	@Override
	public void setField(String key, byte value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}

	@Override
	public void setField(String key, char value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}

	@Override
	public void setField(String key, short value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}

	@Override
	public void setField(String key, int value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}

	@Override
	public void setField(String key, long value) {
		if(finalized) {
			throw new IllegalStateException("Cannot modify a finalized message");
		}
		map.put(key, value);
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("From:<");
		sb.append(from);
		sb.append("> To:<");
		sb.append(to);
		sb.append("> Fields:<");
		sb.append(map.toString());
		sb.append(">");
		return sb.toString();
	}
}
